---
keywords:
- functions
- views
- Funcs
- ScFuncContext
- ScViewContext
- ScExports
description: The function call context provides as a predefined parameter to the smart contract function and allows you to access the functionality that the host sandbox interface provides.
image: /img/logo/WASP_logo_dark.png
---

import Tabs from "@theme/Tabs"
import TabItem from "@theme/TabItem"

# Function Call Context

[Proxy objects](proxies.mdx) provide generic access capabilities to the data on the host. It
is now time to introduce the gateway to the host that allows you to access the
functionality that the host sandbox interface provides. We call this gateway the _function
call context_
, and it is provided as a predefined parameter to the smart contract function. In fact, you can
distinguish two separate flavors of smart contract functions in the IOTA Smart Contracts:

- **Func**, which allows full mutable access to the smart contract state, and always
  results in a state update.
- **View**, which allows only limited, immutable access to the smart contract state, and
  therefore does not result in a state update. Views can be used to efficiently query the
  current state of the smart contract.

To support this function type distinction, Func and View functions each receive a
separate, different function call context. Only the functionality that is necessary for
their implementation can be accessed through their respective contexts, `ScFuncContext`
and `ScViewContext`. ScViewContext provides a limited, immutable subset of the full
functionality provided by ScFuncContext. By having separate context types, compile-time
type-checking can be used to enforce their usage constraints.

An important part of setting up a smart contract is defining exactly which Funcs and Views
are available and informing the host about them. The host will have to dispatch the
function calls to the corresponding smart contract code. To that end, the smart contract
Wasm code will expose an externally callable function named `on_load` that will be called
by the host upon initial loading of the smart contract code. The `on_load` function must
provide the host with the list of Funcs and Views, and specific identifiers that can be
used to invoke them. It uses a special temporary function context named `ScExports`. That
context can be used to provide the host with a function, type, name, and identifier for
each Func and View that can be called in the smart contract.

When the host need to call a smart contract function, it has to do it by invoking a second
externally callable function named `on_call`. The host passes the identifier for the smart
contract Func or View that needs to be invoked. The client Wasm code will then use this
identifier to set up the corresponding function context and call the function. Note that
there are no other parameters necessary because the function can subsequently access any
other function-related data through its context object.

Here is a (simplified) example from the `dividend` example smart contract that showcases
some features of WasmLib:

<Tabs defaultValue="go"
      groupId="language"
      values={[
          {label: 'Go', value: 'go'},
          {label: 'Rust', value: 'rust'},
          {label: 'TypeScript', value: 'ts'},
      ]}>

<TabItem value="go">

```go
func OnLoad() {
    exports := wasmlib.NewScExports()
    exports.AddFunc("divide", funcDivide)
    exports.AddFunc("init", funcInit)
    exports.AddFunc("member", funcMember)
    exports.AddFunc("setOwner", funcSetOwner)
    exports.AddView("getFactor", viewGetFactor)
    exports.AddView("getOwner", viewGetOwner)
}
```

</TabItem>
    <TabItem value="rust">

```rust
fn on_load() {
    let exports = ScExports::new();
    exports.add_func("divide", func_divide);
    exports.add_func("init", func_init);
    exports.add_func("member", func_member);
    exports.add_func("setOwner", func_set_owner);
    exports.add_view("getFactor", view_get_factor);
    exports.add_view("getOwner", view_get_owner);
}
```

</TabItem>
<TabItem value="ts">

```ts
export function on_load(): void {
    let exports = new ScExports();
    exports.addFunc("divide", funcDivide);
    exports.addFunc("init", funcInit);
    exports.addFunc("member", funcMember);
    exports.addFunc("setOwner", funcSetOwner);
    exports.addView("getFactor", viewGetFactor);
    exports.addView("getOwner", viewGetOwner);
}
```

</TabItem>
</Tabs>

The on_load() function first creates the required ScExports context, and
then proceeds to define four Funcs named `divide`, `init`, `member`, and `setOwner`. It
does this by calling the add_func() method of the ScExports context. Next it defines two
Views named `getFactor` and `getOwner` by calling the addView() method of the ScExports
context. The second parameter to these methods is the actual smart contract function
associated with the name specified. These methods will also automatically assign a unique
identifier to the function and then send everything to the host.

In its simplest form this is all that is necessary to initialize a smart contract. To
finalize this example, here is what the skeleton function implementations for the above
smart contract definition would look like:

<Tabs defaultValue="go"
      groupId="language"
      values={[
          {label: 'Go', value: 'go'},
          {label: 'Rust', value: 'rust'},
          {label: 'TypeScript', value: 'ts'},
      ]}>

<TabItem value="go">

```go
func funcDivide(ctx wasmlib.ScFuncContext) {
    ctx.Log("dividend.funcDivide")
}

func funcInit(ctx wasmlib.ScFuncContext) {
    ctx.Log("dividend.funcInit")
}

func funcMember(ctx wasmlib.ScFuncContext) {
    ctx.Log("dividend.funcMember")
}

func funcSetOwner(ctx wasmlib.ScFuncContext) {
    ctx.Log("dividend.funcSetOwner")
}

func viewGetFactor(ctx wasmlib.ScViewContext) {
    ctx.Log("dividend.viewGetFactor")
}

func viewGetOwner(ctx wasmlib.ScViewContext) {
    ctx.Log("dividend.viewGetOwner")
}
```

</TabItem>
<TabItem value="rust">

```rust
fn func_divide(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.divide");
}

fn func_init(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.init");
}

fn func_member(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.member");
}

fn func_set_owner(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.setOwner");
}

fn view_get_factor(ctx: &ScViewContext) {
    ctx.log("Calling dividend.getFactor");
}

fn view_get_owner(ctx: &ScViewContext) {
    ctx.log("Calling dividend.getOwner");
}
```

</TabItem>
<TabItem value="ts">

```ts
export function func_divide(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.divide");
}

export function func_init(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.init");
}

export function func_member(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.member");
}

export function func_set_owner(ctx: &ScFuncContext) {
    ctx.log("Calling dividend.setOwner");
}

export function view_get_factor(ctx: &ScViewContext) {
    ctx.log("Calling dividend.getFactor");
}

export function view_get_owner(ctx: &ScViewContext) {
    ctx.log("Calling dividend.getOwner");
}
```

</TabItem>
</Tabs>

As you can see, each function is provided with a context parameter, which is
conventionally named _ctx_. Notice that the four Funcs are passed an ScFuncContext,
whereas the two Views receive an ScViewContext.

This example also showcases an important feature of the contexts: the `log()` method. This
can be used to log human-readable text to the host's log output. Logging text is the only
way to add tracing to a smart contract, because it does not have any I/O capabilities
other than what the host provides. There is a second logging method, called `trace()`,
that can be used to provide extra debug information to the host's log output. The trace
output can be selectively turned on and off at the host.

In the next section we will introduce the [`schema`](../schema/schema.mdx) tool that
simplifies smart contract programming a lot.
